<template>
  <div class="report-form-page">
    <el-form :model="formData" :rules="rules" ref="reportFormRef" label-position="top" label-width="180px">
      <!-- 任务信息 -->
      <el-card class="form-section">
    <template #header>
      <div class="card-header">
        <span>任务信息</span>
      </div>
    </template>
    <el-row :gutter="20">
      <el-col :span="12">
        <el-form-item label="选择项目" prop="projectId" required>
          <el-select 
            v-model="formData.projectId" 
            placeholder="请选择项目" 
            @change="handleProjectChange"
            style="width: 100%"
            clearable
          >
            <el-option 
              v-for="item in projectOptions" 
              :key="item.id" 
              :label="item.name" 
              :value="item.id" 
            />
          </el-select>
        </el-form-item>
      </el-col>
      <el-col :span="12">
        <el-form-item label="选择任务" prop="taskInfo.id" required>
          <el-select 
            v-model="formData.taskInfo.id" 
            placeholder="请先选择项目" 
            :disabled="!formData.projectId"
            @change="handleTaskChange"
            style="width: 100%"
            clearable
          >
            <el-option 
              v-for="item in taskOptions" 
              :key="item.id" 
              :label="item.name" 
              :value="item.id" 
            />
          </el-select>
        </el-form-item>
      </el-col>
    </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="任务名称">
              <el-input v-model="formData.taskInfo.taskName" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="项目名称">
              <el-input v-model="formData.projectInfo.projectName" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="开始时间">
              <el-input v-model="formData.taskInfo.startTime" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="结束时间">
              <el-input v-model="formData.taskInfo.endTime" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="任务描述">
              <el-input v-model="formData.taskInfo.description" type="textarea"
                :autosize="{ minRows: 2, maxRows: 4 }" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-card>


      <el-card class="form-section">
        <template #header>
          <div class="card-header">
            <span>任务来源</span>
          </div>
        </template>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="来源文件名" prop="taskSource.fileName" required>
              <el-input v-model="formData.taskSource.fileName" placeholder="请输入来源文件名" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="来源文件编号" prop="taskSource.fileNumber" required>
              <el-input v-model="formData.taskSource.fileNumber" placeholder="请输入来源文件编号" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-card>

      <!-- 设备信息卡片 -->
      <el-card class="form-section">
        <template #header>
          <div class="card-header">
            <span>设备信息</span>
          </div>
        </template>

        <el-table :data="formData.deviceInfo" border style="width: 100%" v-if="formData.deviceInfo.length"
          :empty-text="'暂无设备信息'">
          <el-table-column prop="index" label="序号" width="80" align="center">
            <template #default="{ $index }">
              {{ $index + 1 }}
            </template>
          </el-table-column>
          <el-table-column label="设备名称" prop="deviceName" min-width="200" />
          <el-table-column label="设备位置" prop="location" min-width="200" />
        </el-table>

        <el-empty v-else description="暂无设备信息" :image-size="100" />
      </el-card>


      <el-card class="form-section">
        <template #header>
          <div class="card-header">
            <span>试验信息</span>
          </div>
        </template>
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="试验过程描述" prop="experiment.process" required>
              <el-input v-model="formData.experiment.process" type="textarea" :rows="4" placeholder="请详细描述试验过程" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="8">
            <el-form-item label="系统名称" prop="experiment.systemName" required>
              <el-input v-model="formData.experiment.systemName" placeholder="请输入系统名称" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="最高采样率" prop="experiment.maxSampleRate" required>
              <el-input v-model="formData.experiment.maxSampleRate" placeholder="请输入最高采样率" />
            </el-form-item>
          </el-col>
          <el-col :span="8">
            <el-form-item label="采样详情" prop="experiment.sampleDetails" required>
              <el-input v-model="formData.experiment.sampleDetails" placeholder="请输入采样详情" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-card>


      <el-card class="form-section">
        <template #header>
          <div class="card-header">
            <span>试验记录</span>
          </div>
        </template>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="试验文件编号" prop="experimentRecord.fileNumber" required>
              <el-input v-model="formData.experimentRecord.fileNumber" placeholder="请输入试验文件编号" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="试验数据归档号" prop="experimentRecord.archiveNumber" required>
              <el-input v-model="formData.experimentRecord.archiveNumber" placeholder="请输入试验数据归档号" />
            </el-form-item>
          </el-col>
        </el-row>
      </el-card>

      <!-- 负责人信息 -->
      <el-card class="form-section">
        <template #header>
          <div class="card-header">
            <span>负责人信息</span>
          </div>
        </template>
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="负责人">
              <div class="tags-container">
                <el-tag v-for="(name, index) in formData.userDuty.nickName" :key="'duty-' + index" type="info"
                  class="user-tag">
                  {{ name }}
                </el-tag>
                <el-tag v-if="!formData.userDuty.nickName.length" type="info">
                  暂无负责人
                </el-tag>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
      </el-card>

      <!-- 参与人信息 -->
      <el-card class="form-section">
        <template #header>
          <div class="card-header">
            <span>参与人信息</span>
          </div>
        </template>
        <el-row :gutter="20">
          <el-col :span="24">
            <el-form-item label="参与人">
              <div class="tags-container">
                <el-tag v-for="(name, index) in formData.userParticipant.nickName" :key="'participant-' + index"
                  class="user-tag">
                  {{ name }}
                </el-tag>
                <el-tag v-if="!formData.userParticipant.nickName.length" type="info">
                  暂无参与人
                </el-tag>
              </div>
            </el-form-item>
          </el-col>
        </el-row>
      </el-card>

      <!-- 传感器参数 -->
      <el-card class="form-section">
        <template #header>
          <div class="card-header">
            <span>表格1：传感器参数</span>
          </div>
        </template>
        <el-form-item label="表格名称" prop="sensorTableName" required>
          <el-input v-model="formData.sensorTableName" placeholder="请输入传感器参数表格名称" />
        </el-form-item>
        <div class="sensor-actions">
          <el-button type="primary" @click="addSensor" :icon="Plus">
            添加传感器
          </el-button>
          <el-button v-if="formData.sensors.length > 1" type="danger" @click="clearSensors" :icon="Delete">
            清空所有
          </el-button>
        </div>

        <el-table :data="formData.sensors" style="width: 100%; margin-top: 16px" border v-if="formData.sensors.length"
          :empty-text="'暂无传感器数据'">
          <el-table-column prop="index" label="序号" width="80" align="center" />
          <el-table-column label="参数名称" min-width="120">
            <template #default="{ row, $index }">
              <el-input v-model="row.parameterName" placeholder="请输入参数名称"
                :class="{ 'is-error': submitted && !row.parameterName }" @change="validateSensor(row, $index)" />
            </template>
          </el-table-column>
          <el-table-column label="符号" min-width="100">
            <template #default="{ row }">
              <el-input v-model="row.symbol" placeholder="请输入符号" />
            </template>
          </el-table-column>
          <el-table-column label="单位" min-width="100">
            <template #default="{ row }">
              <el-input v-model="row.unit" placeholder="请输入单位" />
            </template>
          </el-table-column>
          <el-table-column label="量程" min-width="120">
            <template #default="{ row }">
              <el-input v-model="row.measureRange" placeholder="请输入量程" />
            </template>
          </el-table-column>
          <el-table-column label="精度" min-width="120">
            <template #default="{ row }">
              <el-input v-model="row.accuracy" placeholder="请输入精度" />
            </template>
          </el-table-column>
          <el-table-column label="位置" min-width="120">
            <template #default="{ row }">
              <el-input v-model="row.location" placeholder="请输入位置" />
            </template>
          </el-table-column>
          <el-table-column label="测点" min-width="120">
            <template #default="{ row }">
              <el-input v-model="row.measurementPoint" placeholder="请输入位置" />
            </template>
          </el-table-column>
          <el-table-column label="操作" width="120" align="center" fixed="right">
            <template #default="{ $index }">
              <el-button type="danger" link @click="removeSensor($index)" :icon="Delete">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
        <el-empty v-else description="暂无传感器数据" :image-size="100">
          <el-button type="primary" @click="addSensor" :icon="Plus">
            添加传感器
          </el-button>
        </el-empty>
      </el-card>
      <!-- 在传感器参数卡片下方添加文件上传卡片 -->
      <el-card class="form-section">
        <template #header>
          <div class="card-header">
            <span>测试文件</span>
          </div>
        </template>

        <!-- 测试方案文件上传 -->
        <el-form-item label="测试方案文件">
          <div class="file-upload-wrapper">
            <el-input v-if="formData.firstPicture" v-model="formData.firstPicture.name" placeholder="请输入测试方案文件名"
              style="margin-bottom: 10px;" clearable />
            <el-upload 
              ref="testPlanUploadRef"
              class="upload-demo" 
              action="/api/common/file" 
              :headers="uploadHeaders" 
              :limit="1"
              :on-success="handleTestPlanSuccess" 
              :on-error="handleTestPlanError" 
              :on-remove="handleTestPlanRemove"
              :on-exceed="handleTestPlanExceed"
              :on-change="handleTestPlanChange"
              :before-upload="handleTestPlanBeforeUpload"
              :file-list="getFirstPictureFileList()" 
              :auto-upload="true" 
              accept="*">
              <el-button type="primary">点击上传</el-button>
              <template #tip>
                <div class="el-upload__tip">请上传测试方案文件（可替换已有文件）</div>
              </template>
            </el-upload>
          </div>
        </el-form-item>

        <!-- 测试数据文件上传 -->
        <el-form-item label="测试数据文件">
          <div class="file-upload-wrapper">
            <el-input v-if="formData.secondPicture" v-model="formData.secondPicture.name" placeholder="请输入测试数据文件名"
              style="margin-bottom: 10px;" clearable />
            <el-upload 
              ref="testDataUploadRef"
              class="upload-demo" 
              action="/api/common/file" 
              :headers="uploadHeaders" 
              :limit="1"
              :on-success="handleTestDataSuccess" 
              :on-error="handleTestDataError" 
              :on-remove="handleTestDataRemove"
              :on-exceed="handleTestDataExceed"
              :on-change="handleTestDataChange"
              :before-upload="handleTestDataBeforeUpload"
              :file-list="getSecondPictureFileList()" 
              :auto-upload="true" 
              accept="*">
              <el-button type="primary">点击上传</el-button>
              <template #tip>
                <div class="el-upload__tip">请上传测试数据文件（可替换已有文件）</div>
              </template>
            </el-upload>
          </div>
        </el-form-item>
      </el-card>
      <!-- 公式参数 -->
      <!-- 公式参数卡片部分修改 -->
      <el-card class="form-section">
        <template #header>
          <div class="card-header">
            <span>公式参数</span>
          </div>
        </template>
        <div class="formula-actions">
          <el-button type="primary" @click="addFormula" :icon="Plus">
            添加公式
          </el-button>
          <el-button v-if="formData.formulas.length > 1" type="danger" @click="clearFormulas" :icon="Delete">
            清空所有
          </el-button>
        </div>

        <el-table :data="formData.formulas" style="width: 100%; margin-top: 16px" border v-if="formData.formulas.length"
          :empty-text="'暂无公式数据'">
          <el-table-column prop="formulaIndex" label="序号" width="80" align="center" />
          <el-table-column label="公式图片" min-width="200">
            <template #default="{ row, $index }">
              <el-upload class="formula-upload" action="/api/common/file" :headers="uploadHeaders" multiple
                :file-list="getFileList(row.fileUrls)" :on-success="(res) => handleFormulaUploadSuccess(res, $index)"
                :on-remove="(file) => handleFormulaRemove(file, $index)">
                <el-button type="primary">上传图片</el-button>
                <template #tip>
                  <div class="el-upload__tip">可上传多张公式图片</div>
                </template>
              </el-upload>
              <div class="formula-preview" v-if="row.fileUrls.length">
                <div v-for="(file, idx) in row.fileUrls" :key="idx" class="preview-item">
                  <el-image :src="file.fileUrl" :preview-src-list="getPreviewSrcList(row.fileUrls)" fit="cover"
                    style="width: 60px; height: 60px; margin-right: 5px;">
                  </el-image>
                  <el-tag size="small" closable @close="removeFormulaImage($index, idx)">
                    {{ `图片${file.pictureIndex}` }}
                  </el-tag>
                </div>
              </div>
            </template>
          </el-table-column>
          <el-table-column label="公式说明" min-width="200">
            <template #default="{ row, $index }">
              <el-input v-model="row.description" placeholder="请输入公式说明"
                :class="{ 'is-error': submitted && !row.description }" />
            </template>
          </el-table-column>
          <el-table-column label="参数说明" min-width="200">
            <template #default="{ row, $index }">
              <el-input v-model="row.valueExplanation" placeholder="请输入参数说明"
                :class="{ 'is-error': submitted && !row.valueExplanation }" />
            </template>
          </el-table-column>
          <el-table-column label="操作" width="120" align="center" fixed="right">
            <template #default="{ $index }">
              <el-button type="danger" link @click="removeFormula($index)" :icon="Delete">删除</el-button>
            </template>
          </el-table-column>
        </el-table>
        <el-empty v-else description="暂无公式数据" :image-size="100">
          <el-button type="primary" @click="addFormula" :icon="Plus">
            添加公式
          </el-button>
        </el-empty>
      </el-card>
      <!-- 在template中添加 -->
      <!-- 统计表卡片 -->
      <el-card class="form-section">
        <template #header>
          <div class="card-header">
            <span>表格2：统计表</span>
          </div>
        </template>
        <el-form-item label="表格名称" prop="statisticalTableName" required>
          <el-input v-model="formData.statisticalTableName" placeholder="请输入统计表名称" />
        </el-form-item>

        <!-- 表头设置 -->
        <div class="header-setting-container">
          <div class="header-setting-title">
            <span>表头设置</span>
            <el-button type="primary" size="small" @click="addStatisticalTableColumn" :icon="Plus" plain>
              添加列
            </el-button>
          </div>
          <div class="header-tags">
            <div 
              v-for="(header, index) in getStatisticalTableHeaders()" 
              :key="index" 
              class="header-tag-item"
            >
              <el-input 
                v-model="formData.statisticalTableData[0][index]" 
                :placeholder="`列${index + 1}标题`"
                size="small"
                class="header-input"
              />
              <el-button 
                v-if="getStatisticalTableHeaders().length > 1"
                type="danger" 
                size="small" 
                :icon="Delete" 
                circle
                @click="removeStatisticalTableColumn(index)"
                class="header-delete-btn"
              />
            </div>
          </div>
        </div>

        <div class="table-actions">
          <el-button type="primary" @click="addStatisticalTableRow" :icon="Plus" size="default">
            添加数据行
          </el-button>
          <el-button 
            v-if="formData.statisticalTableData && formData.statisticalTableData.length > 1" 
            type="danger" 
            @click="clearStatisticalTable" 
            :icon="Delete"
            size="default"
            plain
          >
            清空所有数据
          </el-button>
        </div>

        <el-table :data="getStatisticalTableDataRows()" border stripe class="data-table">
          <el-table-column v-for="(header, colIndex) in getStatisticalTableHeaders()" :key="colIndex"
            :label="header || `列${colIndex + 1}`" min-width="150">
            <template #default="{ row, $index }">
              <el-input 
                v-model="formData.statisticalTableData[$index + 1][colIndex]" 
                :placeholder="`请输入${header || `列${colIndex + 1}`}`"
                size="small"
                clearable
              />
            </template>
          </el-table-column>
          <el-table-column label="操作" width="100" align="center" fixed="right">
            <template #default="{ $index }">
              <el-button type="danger" link size="small" @click="removeStatisticalTableRow($index)" :icon="Delete">
                删除
              </el-button>
            </template>
          </el-table-column>
        </el-table>
      </el-card>
      <!-- 新增附录表卡片 -->
      <el-card class="form-section">
        <template #header>
          <div class="card-header">
            <span>附录表</span>
            <el-input v-model="formData.appendixTableName" placeholder="请输入附录表名称"
              style="width: 300px; margin-left: 20px;" clearable />
          </div>
        </template>

        <!-- 附录表标题设置 -->
        <el-row :gutter="20" style="margin-bottom: 20px;">
          <el-col :span="12">
            <el-form-item label="附录表一标题" prop="appendix1Title">
              <el-input v-model="formData.appendix1Title" placeholder="请输入附录表一标题（用于区分数据）" clearable />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="附录表二标题" prop="appendix2Title">
              <el-input v-model="formData.appendix2Title" placeholder="请输入附录表二标题（用于区分数据）" clearable />
            </el-form-item>
          </el-col>
        </el-row>

        <!-- 附录表表头设置 -->
        <div class="header-setting-container">
          <div class="header-setting-title">
            <span>表头设置</span>
            <el-button type="primary" size="small" @click="addAppendixTableColumn" :icon="Plus" plain>
              添加列
            </el-button>
          </div>
          <div class="header-tags">
            <div 
              v-for="(header, index) in getAppendixTableHeaders()" 
              :key="index" 
              class="header-tag-item"
            >
              <el-input 
                v-model="formData.appendix1TableData[0][index]" 
                :placeholder="`列${index + 1}标题`"
                size="small"
                class="header-input"
              />
              <el-button 
                v-if="getAppendixTableHeaders().length > 1"
                type="danger" 
                size="small" 
                :icon="Delete" 
                circle
                @click="removeAppendixTableColumn(index)"
                class="header-delete-btn"
              />
            </div>
          </div>
        </div>

        <!-- 合并后的附录表 -->
        <div class="appendix-merged-table">
          <div class="table-actions">
            <el-button-group>
              <el-button type="primary" @click="addAppendix1Row" :icon="Plus" size="default">
                添加附录表一数据行
              </el-button>
              <el-button type="primary" @click="addAppendix2Row" :icon="Plus" size="default">
                添加附录表二数据行
              </el-button>
            </el-button-group>
            <el-button 
              v-if="(formData.appendix1TableData && formData.appendix1TableData.length > 1) || (formData.appendix2TableData && formData.appendix2TableData.length > 1)" 
              type="danger" 
              @click="clearAllAppendixTables" 
              :icon="Delete"
              size="default"
              plain
            >
              清空所有数据
            </el-button>
          </div>
          <el-table :data="getMergedAppendixTableRows()" border stripe class="data-table">
            <el-table-column prop="testItem" label="试验项目" width="120" align="center" fixed="left">
              <template #default="{ row }">
                <el-tag :type="row.sourceType === 'appendix1' ? 'primary' : 'success'" effect="plain">
                  {{ row.testItem }}
                </el-tag>
              </template>
            </el-table-column>
            <el-table-column v-for="(header, colIndex) in getAppendixTableHeaders()" :key="colIndex"
              :label="header || `列${colIndex + 1}`" min-width="150">
              <template #default="{ row }">
                <el-input 
                  v-model="row.data[colIndex]" 
                  :placeholder="`请输入${header || `列${colIndex + 1}`}`"
                  size="small"
                  clearable
                />
              </template>
            </el-table-column>
            <el-table-column label="操作" width="100" align="center" fixed="right">
              <template #default="{ row, $index }">
                <el-button type="danger" link size="small" @click="removeMergedAppendixRow(row, $index)" :icon="Delete">
                  删除
                </el-button>
              </template>
            </el-table-column>
          </el-table>
        </div>
      </el-card>

      <!-- 结论 -->
      <el-card class="form-section">
        <template #header>
          <div class="card-header">
            <span>结论</span>
          </div>
        </template>
        <el-form-item prop="conclusion">
          <el-input v-model="formData.conclusion" type="textarea" :rows="6" placeholder="请输入测试结论" maxlength="500"
            show-word-limit :error="reportFormRef?.fields['conclusion']?.validateState === 'error'"
            :error-message="reportFormRef?.fields['conclusion']?.validateMessage" />
        </el-form-item>
      </el-card>

      <!-- 表单操作 -->
      <div class="form-actions">
        <el-button type="primary" @click="handleSubmit" :loading="loading" :icon="Check">
          生成报告
        </el-button>
        <el-button @click="resetForm" :icon="Refresh">
          重置
        </el-button>
        <el-button @click="saveDraft" :disabled="!formData.taskInfo.id" :icon="DocumentAdd">
          保存草稿
        </el-button>
        <el-button @click="loadDraft" :icon="FolderOpened">
          加载草稿
        </el-button>
      </div>
    </el-form>
    <DraftSelectDialog ref="draftDialogRef" @load="handleLoadDraft" />
    <TemplateSelectDialog ref="templateDialogRef" @confirm="handleTemplateConfirm" @cancel="handleTemplateCancel" />

  </div>


</template>

<script setup lang="ts">
import { Message } from '@arco-design/web-vue'
import { ref, reactive, onMounted, nextTick, watch, h } from 'vue'
import {
  ElMessage,
  ElMessageBox,
  type FormInstance,
  type FormRules
} from 'element-plus'
import {
  Delete,
  Plus,
  Check,
  Refresh,
  DocumentAdd,
  FolderOpened
} from '@element-plus/icons-vue'
import { debounce } from 'lodash-es'
import {
  searchTasks,
  searchTaskTemplateInformation,
  generateTestReport,
  saveReportDraft,
  getReportDraft,
  type ReportDataModel,
  type Sensor,
  type TaskOption,
  type FormulaItem,
  type Param,
  type ParamHeaders,
  type FormulasFileUrls
} from '@/apis/template/testReport'
import { useDownload } from '@/hooks'
import { ElInput, type UploadFile, type UploadUserFile } from 'element-plus'
import DraftSelectDialog from './DraftSelectDialog.vue'
import TemplateSelectDialog from './TemplateSelectDialog.vue'
import { useUserStore } from '@/stores/modules/user'
import { 
  listProjectStats,
  listTaskStats
} from '@/apis/task/taskSituationChart'

// 常量定义
const INIT_SENSOR: Sensor = {
  index: 0,
  parameterName: '',
  symbol: '',
  unit: '',
  measureRange: '',
  accuracy: '',
  location: '',
  measurementPoint: ''
}

const INIT_PARAM_HEADERS: ParamHeaders = {
  param1: '参数1',
  param2: '参数2',
  param3: '参数3',
  param4: '参数4',
  param5: '参数5'
}

const INIT_PARAM: Param = {
  index: 0,
  param1: '',
  param2: '',
  param3: '',
  param4: '',
  param5: ''
}

const INIT_FORM_DATA: ReportDataModel = {
  projectId: '',
  taskInfo: {
    id: 0,
    taskName: '',
    description: '',
    startTime: '',
    endTime: ''
  },
  projectInfo: {
    id: 0,
    projectName: ''
  },
  deviceInfo: [],
  userDuty: {
    nickName: [],
    handler: {}
  },
  userParticipant: {
    nickName: [],
    handler: {}
  },
  taskTestTemplate: {
    templateId: 0,
    taskTemplateUrl: ''
  },
  conclusion: '',
  sensors: [{ ...INIT_SENSOR, index: 1 }],
  fileName: '',
  formulas: [],
  taskSource: {
    fileName: '',
    fileNumber: ''
  },
  experiment: {
    process: '',
    systemName: '',
    maxSampleRate: '',
    sampleDetails: ''
  },
  experimentRecord: {
    fileNumber: '',
    archiveNumber: ''
  },
  sensorTableName: '脉动传感器参数表',
  statisticalTableName: '数据统计表',
  appendixTableName: '附录表',
  // 统计表数据（二维数组，第一行为表头）
  statisticalTableData: [['参数1', '参数2', '参数3', '参数4', '参数5']],
  // 附录表1数据（二维数组，第一行为表头）
  appendix1TableData: [['参数1', '参数2', '参数3', '参数4', '参数5']],
  // 附录表2数据（二维数组，第一行为表头）
  appendix2TableData: [['参数1', '参数2', '参数3', '参数4', '参数5']],
  // 附录表标题（用于在合并表格中区分数据）
  appendix1Title: '附录表一',
  appendix2Title: '附录表二'
}

// 状态管理
const reportFormRef = ref<FormInstance>()
const loading = ref(false)
const taskLoading = ref(false)
const submitted = ref(false)
const draftDialogRef = ref<{
  open: () => Promise<void>
}>()
const templateDialogRef = ref<{
  open: () => Promise<void>
}>()
const globalPictureIndex = ref(1)
const pendingSubmit = ref(false) // 标记是否有待提交的请求 
const userStore = useUserStore();
const projectOptions = ref<{id: number, name: string}[]>([])
const taskOptions = ref<{id: number, name: string}[]>([])
const uploadHeaders = {
  Authorization: `Bearer ${userStore.token}`
};
// 文件上传组件引用
const testPlanUploadRef = ref<any>()
const testDataUploadRef = ref<any>()

// 表单数据
let formData = reactive<ReportDataModel>({ ...INIT_FORM_DATA })

// 表单验证规则
const rules = reactive<FormRules>({
  'taskInfo.id': [
    { required: true, message: '请选择任务', trigger: 'change' }
  ],
  'sysFile.name': [
    { required: true, message: '请输入文件名称', trigger: 'blur' },
    { max: 50, message: '长度不超过50个字符', trigger: 'blur' }
  ],
  'sysFile.id': [
    { required: true, message: '请输入文档编号', trigger: 'blur' },
    { type: 'number', message: '必须为数字值', trigger: 'blur' }
  ],
  conclusion: [
    { required: true, message: '请输入测试结论', trigger: 'blur' },
    { min: 10, message: '至少输入10个字符', trigger: 'blur' }
  ],
  'taskSource.fileName': [{ required: true, message: '请输入来源文件名', trigger: 'blur' }],
  'taskSource.fileNumber': [{ required: true, message: '请输入来源文件编号', trigger: 'blur' }],
  'experiment.process': [{ required: true, message: '请输入试验过程描述', trigger: 'blur' }],
  'experiment.systemName': [{ required: true, message: '请输入系统名称', trigger: 'blur' }],
  'experiment.maxSampleRate': [{ required: true, message: '请输入最高采样率', trigger: 'blur' }],
  'experiment.sampleDetails': [{ required: true, message: '请输入采样详情', trigger: 'blur' }],
  'experimentRecord.fileNumber': [{ required: true, message: '请输入试验文件编号', trigger: 'blur' }],
  'experimentRecord.archiveNumber': [{ required: true, message: '请输入试验数据归档号', trigger: 'blur' }],
  'sensorTableName': [{ required: true, message: '请输入传感器参数表格名称', trigger: 'blur' }],
  'statisticalTableName': [{ required: true, message: '请输入统计表名称', trigger: 'blur' }]
})

// 方法定义

const confirmAction = (message: string, title = '警告') => {
  return ElMessageBox.confirm(message, title, {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  })
}

type IndexedItem = { index: number }

interface IndexedListOptions {
  minLength?: number
  minWarning?: string
  confirmMessage?: string
  cancelMessage?: string
  clearToEmpty?: boolean
}

const createIndexedListManager = <T extends IndexedItem>(
  listGetter: () => T[],
  listSetter: (list: T[]) => void,
  createItem: (index: number) => T,
  options: IndexedListOptions = {}
) => {
  const {
    minLength = 1,
    minWarning = '至少保留一行数据',
    confirmMessage = '确定要清空所有数据吗？',
    cancelMessage,
    clearToEmpty = false
  } = options

  const reindex = (list: T[]) => {
    list.forEach((item, idx) => {
      item.index = idx + 1
    })
  }

  const add = () => {
    const list = listGetter()
    list.push(createItem(list.length + 1))
  }

  const remove = (index: number) => {
    const list = listGetter()
    if (list.length <= minLength) {
      ElMessage.warning(minWarning)
      return
    }
    list.splice(index, 1)
    reindex(list)
  }

  const clear = async () => {
    try {
      await confirmAction(confirmMessage)
      const next = clearToEmpty ? [] : [createItem(1)]
      listSetter(next)
    } catch {
      if (cancelMessage) {
        ElMessage.info(cancelMessage)
      }
    }
  }

  const replace = (list: T[]) => {
    if (!Array.isArray(list)) {
      listSetter([])
      return
    }
    const copy = list.map((item, idx) => ({ ...item, index: idx + 1 })) as T[]
    listSetter(copy)
  }

  return {
    add,
    remove,
    clear,
    reindex: () => reindex(listGetter()),
    replace
  }
}

const sensorManager = createIndexedListManager<Sensor>(
  () => formData.sensors,
  (list) => { formData.sensors = list },
  (index) => ({ ...INIT_SENSOR, index }),
  {
    minWarning: '至少保留一个传感器',
    confirmMessage: '确定要清空所有传感器数据吗？',
    cancelMessage: '已取消清空操作'
  }
)

// 统计表辅助函数
const getStatisticalTableHeaders = () => {
  if (!formData.statisticalTableData || formData.statisticalTableData.length === 0) {
    return ['参数1', '参数2', '参数3', '参数4', '参数5']
  }
  return formData.statisticalTableData[0] || []
}

const getStatisticalTableDataRows = () => {
  if (!formData.statisticalTableData || formData.statisticalTableData.length <= 1) {
    return []
  }
  return formData.statisticalTableData.slice(1)
}

const addStatisticalTableRow = () => {
  if (!formData.statisticalTableData || formData.statisticalTableData.length === 0) {
    formData.statisticalTableData = [['序号', '参数1', '参数2', '参数3', '参数4', '参数5']]
  }
  const headerCount = formData.statisticalTableData[0].length
  const newRow = new Array(headerCount).fill('')
  formData.statisticalTableData.push(newRow)
}

const removeStatisticalTableRow = (index: number) => {
  if (formData.statisticalTableData && formData.statisticalTableData.length > index + 1) {
    formData.statisticalTableData.splice(index + 1, 1)
  }
}

const clearStatisticalTable = () => {
  ElMessageBox.confirm('确定要清空所有统计数据吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    if (formData.statisticalTableData && formData.statisticalTableData.length > 0) {
      formData.statisticalTableData = [formData.statisticalTableData[0]]
    }
    ElMessage.success('已清空统计数据')
  }).catch(() => {
    ElMessage.info('已取消清空操作')
  })
}

const addStatisticalTableColumn = () => {
  if (!formData.statisticalTableData || formData.statisticalTableData.length === 0) {
    formData.statisticalTableData = [['参数1', '参数2', '参数3', '参数4', '参数5']]
  }
  const columnIndex = formData.statisticalTableData[0].length
  formData.statisticalTableData[0].push(`参数${columnIndex + 1}`)
  // 为所有数据行添加空值
  for (let i = 1; i < formData.statisticalTableData.length; i++) {
    formData.statisticalTableData[i].push('')
  }
}

const removeStatisticalTableColumn = (columnIndex: number) => {
  if (!formData.statisticalTableData || formData.statisticalTableData.length === 0) {
    return
  }
  
  // 至少保留一列
  if (formData.statisticalTableData[0].length <= 1) {
    ElMessage.warning('至少需要保留一列')
    return
  }
  
  ElMessageBox.confirm('删除此列将同时删除该列的所有数据，确定要删除吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    // 删除表头中的列
    formData.statisticalTableData[0].splice(columnIndex, 1)
    // 删除所有数据行中对应的列
    for (let i = 1; i < formData.statisticalTableData.length; i++) {
      if (formData.statisticalTableData[i].length > columnIndex) {
        formData.statisticalTableData[i].splice(columnIndex, 1)
      }
    }
    ElMessage.success('列已删除')
  }).catch(() => {
    // 取消操作
  })
}

// 附录表辅助函数
const getAppendixTableHeaders = () => {
  if (!formData.appendix1TableData || formData.appendix1TableData.length === 0) {
    return ['参数1', '参数2', '参数3', '参数4', '参数5']
  }
  return formData.appendix1TableData[0] || []
}

const getAppendix1TableDataRows = () => {
  if (!formData.appendix1TableData || formData.appendix1TableData.length <= 1) {
    return []
  }
  return formData.appendix1TableData.slice(1)
}

const getAppendix2TableDataRows = () => {
  if (!formData.appendix2TableData || formData.appendix2TableData.length <= 1) {
    return []
  }
  return formData.appendix2TableData.slice(1)
}

// 获取合并后的附录表数据行
const getMergedAppendixTableRows = () => {
  const rows: Array<{ testItem: string; data: string[]; sourceIndex: number; sourceType: 'appendix1' | 'appendix2' }> = []
  
  // 获取自定义标题，如果没有则使用默认值
  const appendix1Title = formData.appendix1Title || '附录表一'
  const appendix2Title = formData.appendix2Title || '附录表二'
  
  // 添加附录表1的数据
  if (formData.appendix1TableData && formData.appendix1TableData.length > 1) {
    const appendix1Rows = formData.appendix1TableData.slice(1)
    appendix1Rows.forEach((row, index) => {
      rows.push({
        testItem: appendix1Title,
        data: row,
        sourceIndex: index,
        sourceType: 'appendix1'
      })
    })
  }
  
  // 添加附录表2的数据
  if (formData.appendix2TableData && formData.appendix2TableData.length > 1) {
    const appendix2Rows = formData.appendix2TableData.slice(1)
    appendix2Rows.forEach((row, index) => {
      rows.push({
        testItem: appendix2Title,
        data: row,
        sourceIndex: index,
        sourceType: 'appendix2'
      })
    })
  }
  
  return rows
}

// 删除合并表格中的行
const removeMergedAppendixRow = (row: { testItem: string; data: string[]; sourceIndex: number; sourceType: 'appendix1' | 'appendix2' }, index: number) => {
  if (row.sourceType === 'appendix1') {
    if (formData.appendix1TableData && formData.appendix1TableData.length > row.sourceIndex + 1) {
      formData.appendix1TableData.splice(row.sourceIndex + 1, 1)
    }
  } else {
    if (formData.appendix2TableData && formData.appendix2TableData.length > row.sourceIndex + 1) {
      formData.appendix2TableData.splice(row.sourceIndex + 1, 1)
    }
  }
}

// 清空所有附录表数据
const clearAllAppendixTables = () => {
  ElMessageBox.confirm('确定要清空所有附录表数据吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    if (formData.appendix1TableData && formData.appendix1TableData.length > 0) {
      formData.appendix1TableData = [formData.appendix1TableData[0]]
    }
    if (formData.appendix2TableData && formData.appendix2TableData.length > 0) {
      formData.appendix2TableData = [formData.appendix2TableData[0]]
    }
    ElMessage.success('已清空所有附录表数据')
  }).catch(() => {
    ElMessage.info('已取消操作')
  })
}

const addAppendix1Row = () => {
  if (!formData.appendix1TableData || formData.appendix1TableData.length === 0) {
    formData.appendix1TableData = [['参数1', '参数2', '参数3', '参数4', '参数5']]
  }
  const headerCount = formData.appendix1TableData[0].length
  const newRow = new Array(headerCount).fill('')
  formData.appendix1TableData.push(newRow)
  ElMessage.success('已添加附录表一数据行')
}

const removeAppendix1Row = (index: number) => {
  if (formData.appendix1TableData && formData.appendix1TableData.length > index + 1) {
    formData.appendix1TableData.splice(index + 1, 1)
  }
}

const clearAppendix1Table = () => {
  ElMessageBox.confirm('确定要清空附录表1的所有数据吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    if (formData.appendix1TableData && formData.appendix1TableData.length > 0) {
      formData.appendix1TableData = [formData.appendix1TableData[0]]
    }
    ElMessage.success('已清空附录表1数据')
  }).catch(() => {
    ElMessage.info('已取消操作')
  })
}

const addAppendix2Row = () => {
  if (!formData.appendix2TableData || formData.appendix2TableData.length === 0) {
    formData.appendix2TableData = [['参数1', '参数2', '参数3', '参数4', '参数5']]
  }
  const headerCount = formData.appendix2TableData[0].length
  const newRow = new Array(headerCount).fill('')
  formData.appendix2TableData.push(newRow)
  ElMessage.success('已添加附录表二数据行')
}

const removeAppendix2Row = (index: number) => {
  if (formData.appendix2TableData && formData.appendix2TableData.length > index + 1) {
    formData.appendix2TableData.splice(index + 1, 1)
  }
}

const clearAppendix2Table = () => {
  ElMessageBox.confirm('确定要清空附录表2的所有数据吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    if (formData.appendix2TableData && formData.appendix2TableData.length > 0) {
      formData.appendix2TableData = [formData.appendix2TableData[0]]
    }
    ElMessage.success('已清空附录表2数据')
  }).catch(() => {
    ElMessage.info('已取消操作')
  })
}

const addAppendixTableColumn = () => {
  if (!formData.appendix1TableData || formData.appendix1TableData.length === 0) {
    formData.appendix1TableData = [['参数1', '参数2', '参数3', '参数4', '参数5']]
  }
  if (!formData.appendix2TableData || formData.appendix2TableData.length === 0) {
    formData.appendix2TableData = [['参数1', '参数2', '参数3', '参数4', '参数5']]
  }
  const columnIndex = formData.appendix1TableData[0].length
  const newHeader = `参数${columnIndex + 1}`
  
  // 为附录表1添加列
  formData.appendix1TableData[0].push(newHeader)
  for (let i = 1; i < formData.appendix1TableData.length; i++) {
    formData.appendix1TableData[i].push('')
  }
  
  // 为附录表2添加列
  formData.appendix2TableData[0].push(newHeader)
  for (let i = 1; i < formData.appendix2TableData.length; i++) {
    formData.appendix2TableData[i].push('')
  }
}

const removeAppendixTableColumn = (columnIndex: number) => {
  if (!formData.appendix1TableData || formData.appendix1TableData.length === 0) {
    return
  }
  
  // 至少保留一列
  if (formData.appendix1TableData[0].length <= 1) {
    ElMessage.warning('至少需要保留一列')
    return
  }
  
  ElMessageBox.confirm('删除此列将同时删除附录表1和附录表2中该列的所有数据，确定要删除吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    // 删除附录表1中的列
    formData.appendix1TableData[0].splice(columnIndex, 1)
    for (let i = 1; i < formData.appendix1TableData.length; i++) {
      if (formData.appendix1TableData[i].length > columnIndex) {
        formData.appendix1TableData[i].splice(columnIndex, 1)
      }
    }
    
    // 删除附录表2中的列
    if (formData.appendix2TableData && formData.appendix2TableData.length > 0) {
      if (formData.appendix2TableData[0].length > columnIndex) {
        formData.appendix2TableData[0].splice(columnIndex, 1)
      }
      for (let i = 1; i < formData.appendix2TableData.length; i++) {
        if (formData.appendix2TableData[i].length > columnIndex) {
          formData.appendix2TableData[i].splice(columnIndex, 1)
        }
      }
    }
    
    ElMessage.success('列已删除')
  }).catch(() => {
    // 取消操作
  })
}

const handleTaskChange = async (taskId: number) => {
  if (!taskId) return

  try {
    loading.value = true
    const { data } = await searchTaskTemplateInformation(taskId)
    const responseData = data.data as Partial<ReportDataModel> & Record<string, any>
    const taskInfo = (responseData.taskInfo || {}) as Partial<ReportDataModel['taskInfo']>
    formData.taskInfo = {
      id: taskInfo.id || 0,
      taskName: taskInfo.taskName || '',
      description: taskInfo.description || '',
      startTime: taskInfo.startTime || '',
      endTime: taskInfo.endTime || ''
    }

    if (responseData.projectInfo) {
      formData.projectInfo = {
        id: responseData.projectInfo.id || 0,
        projectName: responseData.projectInfo.projectName || ''
      }
    }

    if (responseData.deviceInfo) {
      formData.deviceInfo = responseData.deviceInfo || []
    }

    if (responseData.userDuty) {
      formData.userDuty = {
        nickName: responseData.userDuty.nickName || [],
        handler: responseData.userDuty.handler || {}
      }
    }

    if (responseData.userParticipant) {
      formData.userParticipant = {
        nickName: responseData.userParticipant.nickName || [],
        handler: responseData.userParticipant.handler || {}
      }
    }

    if (responseData.taskTestTemplate) {
      formData.taskTestTemplate = {
        templateId: responseData.taskTestTemplate.templateId || 0,
        taskTemplateUrl: responseData.taskTestTemplate.taskTemplateUrl || ''
      }
    }

    sensorManager.replace(
      Array.isArray(responseData.sensors) && responseData.sensors.length
        ? responseData.sensors
        : [{ ...INIT_SENSOR, index: 1 }]
    )

    // 处理统计表数据（二维数组）
    if (Array.isArray(responseData.statisticalTableData) && responseData.statisticalTableData.length > 0) {
      formData.statisticalTableData = responseData.statisticalTableData
    } else {
      formData.statisticalTableData = [['参数1', '参数2', '参数3', '参数4', '参数5']]
    }

    // 处理附录表1数据（二维数组）
    if (Array.isArray(responseData.appendix1TableData) && responseData.appendix1TableData.length > 0) {
      formData.appendix1TableData = responseData.appendix1TableData
    } else {
      formData.appendix1TableData = [['参数1', '参数2', '参数3', '参数4', '参数5']]
    }

    // 处理附录表2数据（二维数组）
    if (Array.isArray(responseData.appendix2TableData) && responseData.appendix2TableData.length > 0) {
      formData.appendix2TableData = responseData.appendix2TableData
    } else {
      formData.appendix2TableData = [['参数1', '参数2', '参数3', '参数4', '参数5']]
    }

    // 处理附录表标题
    if (responseData.appendix1Title) {
      formData.appendix1Title = responseData.appendix1Title
    } else {
      formData.appendix1Title = '附录表一'
    }
    if (responseData.appendix2Title) {
      formData.appendix2Title = responseData.appendix2Title
    } else {
      formData.appendix2Title = '附录表二'
    }

    ElMessage.success('任务数据加载完成')
  } catch (error) {
    console.error('获取任务详情失败:', error)
    ElMessage.error('获取任务详情失败')
  } finally {
    loading.value = false
  }
}
const loadDraft = () => {
  draftDialogRef.value?.open()
}

const handleLoadDraft = async (draftId: number) => {
  try {
    loading.value = true
    const res = await getReportDraft(draftId.toString())

    if (res.data) {
      const draftData = res.data.data
      
      const formulas = draftData.formulas?.length 
        ? draftData.formulas.map(f => ({
            ...f,
            fileUrls: f.fileUrls || []
          }))
        : [{ ...INIT_FORMULA, formulaIndex: 1 }]

      // 设置所有字段都可编辑，并提供默认值
      const loadedData = {
        projectId:draftData.projectId || '',
        taskInfo: {
          id: draftData.taskInfo?.id || 0,
          taskName: draftData.taskInfo?.taskName || '',
          description: draftData.taskInfo?.description || '',
          startTime: draftData.taskInfo?.startTime || '',
          endTime: draftData.taskInfo?.endTime || ''
        },
        projectInfo: {
          id: draftData.projectInfo?.id || 0,
          projectName: draftData.projectInfo?.projectName || ''
        },
        deviceInfo: draftData.deviceInfo || [],
        userDuty: {
          nickName: draftData.userDuty?.nickName || [],
          handler: draftData.userDuty?.handler || {}
        },
        userParticipant: {
          nickName: draftData.userParticipant?.nickName || [],
          handler: draftData.userParticipant?.handler || {}
        },
        taskTestTemplate: draftData.taskTestTemplate || { templateId: 0, taskTemplateUrl: '' },
        conclusion: draftData.conclusion || '',
        sensors: draftData.sensors?.length ? draftData.sensors : [{ ...INIT_SENSOR, index: 1 }],
        formulas,
        fileName: draftData.fileName || '',
        dataTemplateName: draftData.dataTemplateName || '',
        remark: draftData.remark || '',
        firstPicture: draftData.firstPicture ? convertToUploadFile(draftData.firstPicture) : undefined,
        secondPicture: draftData.secondPicture ? convertToUploadFile(draftData.secondPicture) : undefined,
        taskSource: draftData.taskSource || {
          fileName: '',
          fileNumber: ''
        },
        experiment: draftData.experiment || {
          process: '',
          systemName: '',
          maxSampleRate: '',
          sampleDetails: ''
        },
        experimentRecord: draftData.experimentRecord || {
          fileNumber: '',
          archiveNumber: ''
        },
        sensorTableName: draftData.sensorTableName || '脉动传感器参数表',
        statisticalTableName: draftData.statisticalTableName || '数据统计表',
        appendixTableName: draftData.appendixTableName || '附录表',
        // 统计表数据（二维数组，第一行为表头）
        statisticalTableData: draftData.statisticalTableData?.length 
          ? draftData.statisticalTableData 
          : [['参数1', '参数2', '参数3', '参数4', '参数5']],
        // 附录表1数据（二维数组，第一行为表头）
        appendix1TableData: draftData.appendix1TableData?.length 
          ? draftData.appendix1TableData 
          : [['参数1', '参数2', '参数3', '参数4', '参数5']],
        // 附录表2数据（二维数组，第一行为表头）
        appendix2TableData: draftData.appendix2TableData?.length 
          ? draftData.appendix2TableData 
          : [['参数1', '参数2', '参数3', '参数4', '参数5']],
        // 附录表标题（用于在合并表格中区分数据）
        appendix1Title: draftData.appendix1Title || '附录表一',
        appendix2Title: draftData.appendix2Title || '附录表二'
      }

      // 使用Object.assign确保响应式更新
      Object.assign(formData, loadedData)

      sensorManager.replace(formData.sensors)
      rebuildGlobalPictureIndexes()

      // 重置表单验证状态
      nextTick(() => {
        if (reportFormRef.value) {
          reportFormRef.value.clearValidate()
        }
      })

      ElMessage.success('草稿加载成功')
    }
  } catch (error) {
    console.error('加载草稿失败:', error)
    ElMessage.error('加载草稿失败')
  } finally {
    loading.value = false
  }
}

// 获取项目列表
const fetchProjects = async () => {
  try {
    const res = await listProjectStats()
    if (res.success && res.data) {
      const projectList = (res.data as any)?.data ?? []
      projectOptions.value = projectList.map((item: any) => ({
        id: item.id,
        name: item.name
      }))
    }
  } catch (error) {
    console.error('获取项目列表失败:', error)
    ElMessage.error('获取项目列表失败')
  }
}

// 项目变更时获取任务列表
const handleProjectChange = async (projectId: number) => {
  formData.taskInfo.id = undefined as unknown as number // 清空已选任务
  taskOptions.value = [] // 清空任务选项
  
  if (!projectId) return
  
  try {
    const res = await listTaskStats(projectId)
    if (res.success && res.data) {
      const taskList = (res.data as any)?.data ?? []
      taskOptions.value = taskList.map((item: any) => ({
        id: item.id,
        name: item.name
      }))
    }
  } catch (error) {
    console.error('获取任务列表失败:', error)
    ElMessage.error('获取任务列表失败')
  }
}

//传感器参数部分
const addSensor = () => sensorManager.add()

const removeSensor = (index: number) => sensorManager.remove(index)

const clearSensors = () => sensorManager.clear()

const validateSensor = (sensor: Sensor, index: number) => {
  if (!sensor.parameterName && submitted.value) {
    ElMessage.warning(`请填写第 ${index + 1} 个传感器的参数名称`)
  }
}
//公式部分
const INIT_FORMULA: FormulaItem = {
  formulaIndex: 0,
  fileUrls: [],
  description: '',
  valueExplanation: ''
}

// 辅助方法：将后端返回的文件对象转换为 UploadFile 格式
const convertToUploadFile = (fileObj: any): UploadFile => {
  if (!fileObj) {
    return {} as UploadFile
  }
  // 如果已经是 UploadFile 格式，确保有必要的字段
  if (fileObj.url) {
    return {
      uid: fileObj.uid || Date.now().toString(),
      name: fileObj.name || '文件',
      url: fileObj.url,
      status: 'success' as const,
      response: fileObj.response || { data: { url: fileObj.url } }
    } as UploadFile
  }
  // 如果是对象但没有 url，尝试从 response 中提取
  if (typeof fileObj === 'object' && fileObj.response?.data?.url) {
    return {
      uid: fileObj.uid || Date.now().toString(),
      name: fileObj.name || '文件',
      url: fileObj.response.data.url,
      status: 'success' as const,
      response: fileObj.response
    } as UploadFile
  }
  // 其他情况直接返回（可能是已经是 UploadFile 格式）
  return {
    ...fileObj,
    uid: fileObj.uid || Date.now().toString(),
    status: fileObj.status || 'success'
  } as UploadFile
}

// 辅助方法：将fileUrls转换为el-upload需要的格式
const getFileList = (fileUrls: FormulasFileUrls[] | null | undefined) => {
  if (!fileUrls) return []
  return fileUrls.map(file => ({
    name: '公式图片',
    url: file.fileUrl,
    response: { data: { url: file.fileUrl } }
  }))
}

// 辅助方法：获取预览图片列表
const getPreviewSrcList = (fileUrls: FormulasFileUrls[]) => {
  return fileUrls.map(file => file.fileUrl)
}

// 添加公式相关方法
const addFormula = () => {
  formData.formulas.push({
    formulaIndex: formData.formulas.length + 1, // 公式序号从1开始
    fileUrls: [],
    description: '',
    valueExplanation: ''
  })
}

const removeFormula = (index: number) => {
  if (formData.formulas.length <= 1) {
    ElMessage.warning('至少保留一个公式')
    return
  }

  formData.formulas.splice(index, 1)
  
  // 重新编号公式序号
  formData.formulas.forEach((formula, idx) => {
    formula.formulaIndex = idx + 1
  })

  // 重建全局图片序号
  rebuildGlobalPictureIndexes()
}

const handleFormulaUploadSuccess = (response: any, formulaIndex: number) => {
  const formula = formData.formulas[formulaIndex]
  if (!formula.fileUrls) {
    formula.fileUrls = []
  }

  // 添加图片，使用全局递增的pictureIndex
  formula.fileUrls.push({
    fileUrl: response.data.url,
    pictureIndex: globalPictureIndex.value.toString() // 转为字符串保持现有类型
  })

  // 全局序号递增
  globalPictureIndex.value++

  ElMessage.success('公式图片上传成功')
}


const clearFormulas = async () => {
  try {
    await confirmAction('确定要清空所有公式数据吗？')
    formData.formulas = []
    globalPictureIndex.value = 1
  } catch {
    ElMessage.info('已取消清空操作')
  }
}


const handleFormulaRemove = (file: UploadFile, formulaIndex: number) => {
  const uploadResponse = (file.response as Record<string, any> | undefined)?.data
  const url = file.url || uploadResponse?.url
  if (url) {
    const formula = formData.formulas[formulaIndex]
    formula.fileUrls = formula.fileUrls.filter(file => file.fileUrl !== url)

    // 重新编号剩余图片
    formula.fileUrls.forEach((file, idx) => {
      file.pictureIndex = (idx + 1).toString()
    })
  }
}

const removeFormulaImage = (formulaIndex: number, imageIndex: number) => {
  const formula = formData.formulas[formulaIndex]
  if (!formula || !formula.fileUrls?.[imageIndex]) return

  // 删除指定图片
  formula.fileUrls.splice(imageIndex, 1)

  // 重新计算所有图片的全局序号（如果需要严格连续）
  rebuildGlobalPictureIndexes()
}

// 重建全局图片序号
const rebuildGlobalPictureIndexes = () => {
  let index = 1
  formData.formulas.forEach(formula => {
    if (formula.fileUrls) {
      formula.fileUrls.forEach(file => {
        file.pictureIndex = index.toString()
        index++
      })
    }
  })
  globalPictureIndex.value = index
}

// 旧的函数已移除，现在使用新的二维数组操作函数


const validateForm = async () => {
  try {
    await reportFormRef.value?.validate()

    // 验证传感器数据
    const invalidSensor = formData.sensors.find(s => !s.parameterName)
    if (invalidSensor) {
      ElMessage.warning('请填写所有传感器的参数名称')
      return false
    }

    // 验证公式数据
    const invalidFormula = formData.formulas.find(f =>
      !f.fileUrls || !f.description || !f.valueExplanation
    )

    // 验证统计表数据（二维数组格式，至少需要表头行）
    if (!formData.statisticalTableData || formData.statisticalTableData.length < 1) {
      ElMessage.warning('请填写所有统计表的必填项')
      return false
    }
    if (invalidFormula) {
      ElMessage.warning('请完善所有公式信息（图片、说明和参数说明）')
      return false
    }
    return true
  } catch (error) {
    console.error('表单验证失败:', error)
    return false
  }
}

const handleSubmit = async () => {
  submitted.value = true

  if (!await validateForm()) {
    return
  }

  // 先弹出模板选择对话框
  pendingSubmit.value = true
  templateDialogRef.value?.open()
}

// 准备提交数据，转换文件格式为后端期望的格式
const prepareSubmitData = (): ReportDataModel => {
  const submitData = JSON.parse(JSON.stringify(formData)) as ReportDataModel

  // 转换 firstPicture 格式
  if (submitData.firstPicture) {
    const fileObj = submitData.firstPicture as any
    submitData.firstPicture = {
      name: fileObj.name || '测试方案文件',
      url: fileObj.url || (fileObj.response?.data?.url) || ''
    } as any
  }

  // 转换 secondPicture 格式
  if (submitData.secondPicture) {
    const fileObj = submitData.secondPicture as any
    submitData.secondPicture = {
      name: fileObj.name || '测试数据文件',
      url: fileObj.url || (fileObj.response?.data?.url) || ''
    } as any
  }

  return submitData
}

// 处理模板选择确认
const handleTemplateConfirm = async (template: { id: number; filePath: string }) => {
  try {
    // 将选择的模板信息填入taskTestTemplate
    formData.taskTestTemplate = {
      templateId: template.id,
      taskTemplateUrl: template.filePath
    }

    // 执行生成报告
    loading.value = true

    // 添加文件名生成逻辑
    if (!formData.fileName) {
      formData.fileName = `测试报告_${formData.taskInfo.taskName}_${new Date().toISOString().slice(0, 10)}`
    }

    // 准备提交数据，转换文件格式
    const submitData = prepareSubmitData()
    await useDownload(() => generateTestReport(submitData))
    ElMessage.success('报告生成成功')
  } catch (error) {
    console.error('生成报告失败:', error)
    ElMessage.error('报告生成失败')
  } finally {
    loading.value = false
    pendingSubmit.value = false
  }
}

// 处理模板选择取消
const handleTemplateCancel = () => {
  pendingSubmit.value = false
}

const resetForm = async () => {
  try {
    await confirmAction('确定要重置表单吗？所有未保存的数据将丢失', '提示')

    // 完全重置表单数据
    Object.keys(INIT_FORM_DATA).forEach(key => {
      formData[key] = JSON.parse(JSON.stringify(INIT_FORM_DATA[key]))
    })

    sensorManager.replace(formData.sensors)
    rebuildGlobalPictureIndexes()
    globalPictureIndex.value = 1

    // 重置上传文件
    formData.firstPicture = undefined
    formData.secondPicture = undefined

    // 重置表单验证状态
    if (reportFormRef.value) {
      reportFormRef.value.resetFields()
    }

    submitted.value = false
    Message.success('表单已重置')
  } catch {
    ElMessage.info('已取消重置操作')
  }
}

// 获取测试方案文件的 file-list 格式
const getFirstPictureFileList = (): UploadFile[] => {
  if (!formData.firstPicture) {
    return []
  }
  // 如果是对象且有 url 属性，转换为 UploadFile 数组
  const fileObj = formData.firstPicture as any
  if (fileObj && typeof fileObj === 'object' && fileObj.url) {
    return [{
      uid: fileObj.uid || Date.now().toString(),
      name: fileObj.name || '测试方案文件',
      url: fileObj.url,
      status: 'success' as const,
      response: fileObj.response || { data: { url: fileObj.url } }
    } as UploadFile]
  }
  // 如果已经是数组格式，直接返回
  if (Array.isArray(fileObj)) {
    return fileObj
  }
  // 其他情况返回空数组
  return []
}

// 获取测试数据文件的 file-list 格式
const getSecondPictureFileList = (): UploadFile[] => {
  if (!formData.secondPicture) {
    return []
  }
  // 如果是对象且有 url 属性，转换为 UploadFile 数组
  const fileObj = formData.secondPicture as any
  if (fileObj && typeof fileObj === 'object' && fileObj.url) {
    return [{
      uid: fileObj.uid || Date.now().toString(),
      name: fileObj.name || '测试数据文件',
      url: fileObj.url,
      status: 'success' as const,
      response: fileObj.response || { data: { url: fileObj.url } }
    } as UploadFile]
  }
  // 如果已经是数组格式，直接返回
  if (Array.isArray(fileObj)) {
    return fileObj
  }
  // 其他情况返回空数组
  return []
}

const handleTestPlanSuccess = (response: any, uploadFile: UploadFile) => {
  try {
    // 处理多种可能的响应格式
    let fileUrl: string | undefined
    
    // 尝试多种可能的响应格式
    if (response?.data?.url) {
      fileUrl = response.data.url
    } else if (response?.response?.data?.url) {
      fileUrl = response.response.data.url
    } else if (response?.url) {
      fileUrl = response.url
    } else if (uploadFile?.response && typeof uploadFile.response === 'object' && 'data' in uploadFile.response) {
      const responseData = (uploadFile.response as any).data
      if (responseData?.url) {
        fileUrl = responseData.url
      }
    } else if (uploadFile?.url) {
      fileUrl = uploadFile.url
    }
    
    if (!fileUrl) {
      console.error('文件上传响应格式异常:', { response, uploadFile })
      ElMessage.error('文件上传失败：未获取到文件URL')
      formData.firstPicture = undefined
      return
    }

    // 创建符合后端期望的数据结构，同时保持 UploadFile 格式用于显示
    let fileName = uploadFile.name || '测试方案文件'
    if (!uploadFile.name && uploadFile.response && typeof uploadFile.response === 'object' && 'data' in uploadFile.response) {
      const responseData = (uploadFile.response as any).data
      if (responseData?.name) {
        fileName = responseData.name
      }
    }
    
    formData.firstPicture = {
      uid: uploadFile.uid || Date.now().toString(),
      name: fileName,
      url: fileUrl,
      status: 'success' as const,
      response: response || uploadFile.response || { data: { url: fileUrl } }
    } as any

    // 确保视图更新
    nextTick(() => {
      // file-list 会自动响应式更新，因为 formData 是响应式的
    })

    ElMessage.success('测试方案文件上传成功')
  } catch (error) {
    console.error('处理测试方案文件上传成功回调时出错:', error)
    ElMessage.error('处理文件上传结果时出错')
    formData.firstPicture = undefined
  }
}

const handleTestDataSuccess = (response: any, uploadFile: UploadFile) => {
  try {
    // 处理多种可能的响应格式
    let fileUrl: string | undefined
    
    // 尝试多种可能的响应格式
    if (response?.data?.url) {
      fileUrl = response.data.url
    } else if (response?.response?.data?.url) {
      fileUrl = response.response.data.url
    } else if (response?.url) {
      fileUrl = response.url
    } else if (uploadFile?.response && typeof uploadFile.response === 'object' && 'data' in uploadFile.response) {
      const responseData = (uploadFile.response as any).data
      if (responseData?.url) {
        fileUrl = responseData.url
      }
    } else if (uploadFile?.url) {
      fileUrl = uploadFile.url
    }
    
    if (!fileUrl) {
      console.error('文件上传响应格式异常:', { response, uploadFile })
      ElMessage.error('文件上传失败：未获取到文件URL')
      formData.secondPicture = undefined
      return
    }

    // 创建符合后端期望的数据结构，同时保持 UploadFile 格式用于显示
    let fileName = uploadFile.name || '测试数据文件'
    if (!fileName && uploadFile.response && typeof uploadFile.response === 'object' && 'data' in uploadFile.response) {
      const responseData = (uploadFile.response as any).data
      fileName = responseData?.name || '测试数据文件'
    }
    
    formData.secondPicture = {
      uid: uploadFile.uid || Date.now().toString(),
      name: fileName,
      url: fileUrl,
      status: 'success' as const,
      response: response || uploadFile.response || { data: { url: fileUrl } }
    } as any

    // 确保视图更新
    nextTick(() => {
      // file-list 会自动响应式更新，因为 formData 是响应式的
    })

    ElMessage.success('测试数据文件上传成功')
  } catch (error) {
    console.error('处理测试数据文件上传成功回调时出错:', error)
    ElMessage.error('处理文件上传结果时出错')
    formData.secondPicture = undefined
  }
}

const handleTestPlanError = (error: Error, uploadFile: UploadFile) => {
  console.error('测试方案文件上传失败:', error, uploadFile)
  ElMessage.error(`测试方案文件上传失败: ${error.message || '未知错误'}`)
  // 清除失败的文件
  formData.firstPicture = undefined
}

const handleTestDataError = (error: Error, uploadFile: UploadFile) => {
  console.error('测试数据文件上传失败:', error, uploadFile)
  ElMessage.error(`测试数据文件上传失败: ${error.message || '未知错误'}`)
  // 清除失败的文件
  formData.secondPicture = undefined
}

// 处理测试方案文件变化（当用户选择新文件时）
const handleTestPlanChange = (file: UploadFile, fileList: UploadUserFile[]) => {
  // 如果用户选择了新文件，且已有旧文件，先清除旧文件数据
  if (file.status === 'ready' && formData.firstPicture) {
    // 新文件准备上传，清除旧文件
    formData.firstPicture = undefined
  }
}

// 处理测试方案文件上传前，如果已有文件则先清除
const handleTestPlanBeforeUpload = (file: File) => {
  // 确保旧文件已清除
  if (formData.firstPicture) {
    formData.firstPicture = undefined
  }
  return true
}

// 处理测试方案文件超出限制（当 limit=1 且已有文件时）
const handleTestPlanExceed = (files: File[], uploadFiles: UploadUserFile[]) => {
  // 清除旧文件数据
  formData.firstPicture = undefined
  // 清除上传组件的文件列表
  if (testPlanUploadRef.value) {
    const uploadComponent = testPlanUploadRef.value as any
    if (uploadComponent.clearFiles) {
      uploadComponent.clearFiles()
    }
  }
  ElMessage.info('将替换已有文件，请重新选择文件上传')
}

// 处理测试数据文件变化（当用户选择新文件时）
const handleTestDataChange = (file: UploadFile, fileList: UploadUserFile[]) => {
  // 如果用户选择了新文件，且已有旧文件，先清除旧文件数据
  if (file.status === 'ready' && formData.secondPicture) {
    // 新文件准备上传，清除旧文件
    formData.secondPicture = undefined
  }
}

// 处理测试数据文件上传前，如果已有文件则先清除
const handleTestDataBeforeUpload = (file: File) => {
  // 确保旧文件已清除
  if (formData.secondPicture) {
    formData.secondPicture = undefined
  }
  return true
}

// 处理测试数据文件超出限制（当 limit=1 且已有文件时）
const handleTestDataExceed = (files: File[], uploadFiles: UploadUserFile[]) => {
  // 清除旧文件数据
  formData.secondPicture = undefined
  // 清除上传组件的文件列表
  if (testDataUploadRef.value) {
    const uploadComponent = testDataUploadRef.value as any
    if (uploadComponent.clearFiles) {
      uploadComponent.clearFiles()
    }
  }
  ElMessage.info('将替换已有文件，请重新选择文件上传')
}

const handleTestPlanRemove = () => {
  formData.firstPicture = undefined
  ElMessage.info('已移除测试方案文件')
}

const handleTestDataRemove = () => {
  formData.secondPicture = undefined
  ElMessage.info('已移除测试数据文件')
}
const saveDraft = async () => {
  if (!formData.taskInfo.id) {
    ElMessage.warning('请先选择任务')
    return
  }

  try {
    await ElMessageBox({
      title: '保存草稿',
      message: () => h('div', null, [
        h('div', { class: 'draft-input-row' }, [
          h('span', { class: 'draft-label' }, '草稿名称:'),
          h(ElInput, {
            modelValue: formData.dataTemplateName || '',
            'onUpdate:modelValue': (val: string) => formData.dataTemplateName = val,
            placeholder: '请输入草稿名称'
          })
        ]),
        h('div', { class: 'draft-input-row' }, [
          h('span', { class: 'draft-label' }, '备注:'),
          h(ElInput, {
            modelValue: formData.remark || '',
            'onUpdate:modelValue': (val: string) => formData.remark = val,
            placeholder: '请输入备注（可选）',
            type: 'textarea',
            rows: 3
          })
        ])
      ]),
      showCancelButton: true,
      confirmButtonText: '保存',
      cancelButtonText: '取消',
      customClass: 'draft-save-dialog',
      beforeClose: async (action, instance, done) => {
        if (action === 'confirm') {
          if (!formData.dataTemplateName) {
            ElMessage.warning('草稿名称不能为空')
            return
          }
          loading.value = true
          try {
            // 准备保存数据，转换文件格式
            const submitData = prepareSubmitData()
            await saveReportDraft(submitData)
            ElMessage.success('草稿保存成功')
            done()
          } catch (error) {
            console.error('保存草稿失败:', error)
            ElMessage.error('草稿保存失败')
          } finally {
            loading.value = false
          }
        } else {
          done()
        }
      }
    })
  } catch (error) {
    if (error !== 'cancel') {
      console.error('保存草稿失败:', error)
      ElMessage.error('草稿保存失败')
    }
  }
}


// 初始化
onMounted(() => {
  fetchProjects()
})
</script>

<style scoped lang="scss">
.report-form-page {
  padding: 20px;
  max-width: 1400px;
  margin: 0 auto;
  overflow-y: scroll;

  .toolbar {
    display: flex;
    justify-content: flex-end;
    gap: 12px;
    margin-bottom: 16px;
  }

  .form-section {
    margin-bottom: 24px;
    border-radius: 8px;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.06);
    transition: box-shadow 0.3s;

    &:hover {
      box-shadow: 0 4px 12px rgba(0, 0, 0, 0.1);
    }

    .el-table {
      :deep(.cell) {
        padding: 8px 12px;
      }

      :deep(th) {
        background-color: #f5f7fa;
      }
    }

    .data-table {
      margin-top: 12px;

      :deep(.el-table__header) {
        th {
          background-color: #f5f7fa;
          font-weight: 600;
          color: var(--el-text-color-primary);
        }
      }

      :deep(.el-table__body) {
        tr {
          &:hover {
            background-color: #f5f7fa;
          }
        }

        td {
          padding: 12px 0;

          .el-input {
            width: 100%;
          }
        }
      }
    }

    &:not(:last-child) {
      border-bottom: 1px solid var(--el-border-color-light);
      padding-bottom: 16px;
    }

    .card-header {
      font-weight: 600;
      font-size: 16px;
      color: var(--el-text-color-primary);
    }

    .sensor-actions {
      margin-bottom: 16px;
    }

    .tags-container {
      display: flex;
      flex-wrap: wrap;
      gap: 8px;

      .user-tag {
        margin-right: 0;
      }
    }
  }

  .form-actions {
    display: flex;
    justify-content: center;
    gap: 16px;
    margin-top: 24px;
    margin-bottom: 16px;

    .el-button {
      min-width: 120px;
    }
  }

  :deep(.is-error) {

    .el-input__inner,
    .el-textarea__inner {
      border-color: var(--el-color-danger);
    }
  }

  .formula-upload {
    :deep(.el-upload-list) {
      max-height: 100px;
      overflow-y: auto;
    }
  }

  .template-actions {
    display: flex;
    justify-content: flex-end;
    margin-bottom: 12px;
  }

  .template-upload {
    :deep(.el-upload) {
      margin-bottom: 8px;
    }
    :deep(.el-upload-list__item) {
      margin-top: 4px;
    }
  }

  .formula-preview {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 10px;

    .preview-item {
      display: flex;
      flex-direction: column;
      align-items: center;

      .el-image {
        border: 1px solid #eee;
        border-radius: 4px;
      }

      .el-tag {
        margin-top: 5px;
        cursor: pointer;
      }
    }
  }

  .draft-save-dialog {
    .draft-input-row {
      display: flex;
      align-items: center;
      margin-bottom: 16px;
      gap: 12px;
      align-items: center;
      margin-bottom: 16px;

      .draft-label {
        width: 80px;
        margin-right: 12px;
        text-align: right;
      }

      .el-input,
      .el-textarea {
        flex: 1;
      }
    }
  }

  .formula-upload {
    .el-upload {
      width: 100%;
    }

    .el-upload-list__item {
      margin-top: 0;
    }
  }

  .header-setting-container {
    margin-bottom: 20px;
    padding: 16px;
    background: #f8f9fa;
    border-radius: 8px;
    border: 1px solid #e4e7ed;

    .header-setting-title {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 12px;
      font-weight: 600;
      color: var(--el-text-color-primary);
      font-size: 14px;
    }

    .header-tags {
      display: flex;
      flex-wrap: wrap;
      gap: 12px;
      align-items: flex-start;

      .header-tag-item {
        display: flex;
        align-items: center;
        gap: 8px;
        background: white;
        padding: 8px 12px;
        border-radius: 6px;
        border: 1px solid #dcdfe6;
        transition: all 0.3s;
        min-width: 180px;

        &:hover {
          border-color: var(--el-color-primary);
          box-shadow: 0 2px 8px rgba(64, 158, 255, 0.1);
        }

        .header-input {
          flex: 1;
          min-width: 120px;
        }

        .header-delete-btn {
          flex-shrink: 0;
          width: 24px;
          height: 24px;
          padding: 0;
        }
      }
    }
  }

  .header-setting {
    margin-bottom: 16px;

    .el-col {
      padding-right: 10px;

      &:last-child {
        padding-right: 0;
      }
    }
  }

  .device-actions {
    margin-bottom: 16px;
    display: flex;
    justify-content: flex-end;
  }

  .table-actions {
    display: flex;
    gap: 12px;
    margin-bottom: 16px;
    padding: 12px 0;
    border-bottom: 1px solid #e4e7ed;
  }

  .param-actions {
    margin-bottom: 16px;

    .upload-demo {
      width: 100%;

      .el-upload__tip {
        margin-top: 8px;
        color: var(--el-text-color-secondary);
        font-size: 12px;
      }

      .el-upload-list__item {
        transition: all 0.3s;

        &:hover {
          background-color: var(--el-fill-color-light);
        }
      }
    }
  }

  .appendix-subtable {
    margin-top: 24px;
    padding: 16px;
    background: #fafbfc;
    border-radius: 8px;
    border: 1px solid #e4e7ed;

    h4 {
      margin: 0 0 16px 0;
      font-size: 16px;
      font-weight: 600;
      color: var(--el-text-color-primary);
      padding-bottom: 12px;
      border-bottom: 2px solid var(--el-color-primary);
    }
  }

  .appendix-header-setting {
    margin-bottom: 20px;
    padding: 15px;
    background-color: #f8f8f8;
    border-radius: 4px;

    h4 {
      margin-bottom: 15px;
      color: var(--el-text-color-primary);
    }
  }

  .appendix-merged-table {
    margin-top: 20px;

    .table-actions {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 16px;
      padding: 12px 0;
      border-bottom: 1px solid #e4e7ed;

      .el-button-group {
        display: flex;
        gap: 8px;
      }
    }

    .data-table {
      :deep(.el-table__header) {
        th {
          background-color: #f5f7fa;
          font-weight: 600;
          color: var(--el-text-color-primary);
        }
      }

      :deep(.el-table__body) {
        tr {
          &:hover {
            background-color: #f5f7fa;
          }
        }

        td {
          padding: 12px 0;

          .el-input {
            width: 100%;
          }
        }
      }
    }
  }

  .appendix-subtable {
    margin-top: 24px;
    padding: 16px;
    background: #fafbfc;
    border-radius: 8px;
    border: 1px solid #e4e7ed;

    h4 {
      margin: 0 0 16px 0;
      font-size: 16px;
      font-weight: 600;
      color: var(--el-text-color-primary);
      padding-bottom: 12px;
      border-bottom: 2px solid var(--el-color-primary);
    }
  }

  .formula-preview {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 10px;

    .preview-item {
      display: flex;
      flex-direction: column;
      align-items: center;
    }
  }
}
</style>